"""
主题: 简单的客户端认证
问题: 你想在分布式系统中实现一个简单的客户端连接认证功能，又不想像SSL那样的复杂。
提示 : 
"""

'''
实现一个简单而高效的认证过程:客户端和服务器同时利用hmac和一个只有双方知道的密钥来计算出一个加密哈希值。
然后客户端将它计算出的摘要发送给服务器， 服务器通过比较这个值和自己计算的是否一致来决定接受或拒绝连接
'''

import hmac
import os

def client_authenticate(connection, secret_key):
    '''
    Authenticate client to a remote service.
    connection represents a network connection.
    secret_key is a key known only to both client/server.
    '''
    message = connection.recv(32)
    hash_code = hmac.new(secret_key, message, digestmod='MD5')
    digest = hash_code.digest()
    connection.send(digest)

def server_authenticate(connection, secret_key):
    '''
    Request client authentication.
    '''
    message = os.urandom(32)
    connection.send(message)
    hash_code = hmac.new(secret_key, message, digestmod='MD5')
    digest = hash_code.digest()
    response = connection.recv(len(digest))
    return hmac.compare_digest(digest,response)


'''
对于sockets，服务器代码应该类似下面
'''
from socket import socket, AF_INET, SOCK_STREAM

secret_key = b'peekaboo'
def echo_handler(client_sock):
    if not server_authenticate(client_sock, secret_key):
        client_sock.close()
        return
    while True:

        msg = client_sock.recv(8192)
        if not msg:
            break
        client_sock.sendall(msg)

def echo_server(address):
    s = socket(AF_INET, SOCK_STREAM)
    s.bind(address)
    s.listen(5)
    while True:
        c,a = s.accept()
        echo_handler(c)

if __name__ == '__main__':
    echo_server(('', 20001))
